package com.example.filefusion.service;

import com.example.filefusion.entity.FileChunk;
import io.minio.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;

@Service
public class ChunkService {

    private static final Logger logger = LoggerFactory.getLogger(ChunkService.class);

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucket-name}")
    private String bucketName;

    /**
     * 上传文件分片
     * @param file 文件分片
     * @param chunk 分片信息
     * @return 是否上传成功
     * @throws Exception 异常
     */
    public boolean uploadChunk(MultipartFile file, FileChunk chunk) throws Exception {
        logger.info("开始上传分片: identifier={}, chunkNumber={}, size={}", 
                   chunk.getIdentifier(), chunk.getChunkNumber(), file.getSize());
        
        // 检查bucket是否存在，不存在则创建
        logger.info("检查存储桶是否存在: bucketName={}", bucketName);
        boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!exists) {
            logger.info("存储桶不存在，正在创建: bucketName={}", bucketName);
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            logger.info("存储桶创建成功: bucketName={}", bucketName);
        } else {
            logger.info("存储桶已存在: bucketName={}", bucketName);
        }

        // 构造分片文件名
        String chunkFileName = chunk.getIdentifier() + "_" + chunk.getChunkNumber();
        logger.info("构造分片文件名: chunkFileName={}", chunkFileName);

        // 上传分片到MinIO
        logger.info("开始上传分片到 MinIO: bucketName={}, objectName={}", bucketName, chunkFileName);
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(chunkFileName)
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .build()
        );
        logger.info("分片上传成功: identifier={}, chunkNumber={}", chunk.getIdentifier(), chunk.getChunkNumber());

        return true;
    }

    /**
     * 检查分片是否存在
     * @param chunk 分片信息
     * @return 是否存在
     * @throws Exception 异常
     */
    public boolean checkChunk(FileChunk chunk) throws Exception {
        logger.info("开始检查分片是否存在: identifier={}, number={}", chunk.getIdentifier(), chunk.getChunkNumber());
        String chunkFileName = chunk.getIdentifier() + "_" + chunk.getChunkNumber();
        
        try {
            logger.info("检查MinIO中分片状态: bucketName={}, objectName={}", bucketName, chunkFileName);
            minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(chunkFileName)
                            .build()
            );
            logger.info("分片存在: identifier={}, number={}", chunk.getIdentifier(), chunk.getChunkNumber());
            return true;
        } catch (Exception e) {
            logger.info("分片不存在或检查失败: identifier={}, number={}, error={}", chunk.getIdentifier(), chunk.getChunkNumber(), e.getMessage());
            return false;
        }
    }

    /**
     * 合并分片
     * @param chunk 分片信息
     * @return 合并后的文件名
     * @throws Exception 异常
     */
    public String mergeChunks(FileChunk chunk) throws Exception {
        logger.info("开始合并分片: identifier={}, filename={}, totalChunks={}", chunk.getIdentifier(), chunk.getFilename(), chunk.getTotalChunks());
        
        // 生成唯一文件名
        String fileName = chunk.getIdentifier() + "-" + chunk.getFilename();
        logger.info("生成合并后文件名: fileName={}", fileName);

        // 创建复合对象上传器
        ComposeSource[] sources = new ComposeSource[(int) chunk.getTotalChunks()];
        
        for (int i = 0; i < chunk.getTotalChunks(); i++) {
            String chunkFileName = chunk.getIdentifier() + "_" + (i + 1);
            sources[i] = ComposeSource.builder()
                    .bucket(bucketName)
                    .object(chunkFileName)
                    .build();            
            logger.info("准备合并分片: index={}, chunkFileName={}", i, chunkFileName);
        }

        // 合并分片
        logger.info("执行分片合并操作: bucketName={}, objectName={}", bucketName, fileName);
        minioClient.composeObject(
                ComposeObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .sources(Arrays.asList(sources))
                        .build()
        );
        logger.info("分片合并完成: fileName={}", fileName);

        // 删除分片文件
        logger.info("开始删除分片文件，共 {} 个", chunk.getTotalChunks());
        for (int i = 0; i < chunk.getTotalChunks(); i++) {
            String chunkFileName = chunk.getIdentifier() + "_" + (i + 1);
            logger.info("删除分片文件: chunkFileName={}", chunkFileName);
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(chunkFileName)
                            .build()
            );
        }
        logger.info("分片文件删除成功");

        return fileName;
    }
}